package com.example.concurrency.countdownlatch;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;

public class CountDownLatchDemo implements Runnable
{
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 100,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(5),
            new ThreadPoolExecutor.DiscardPolicy());

    private String name;

    public CountDownLatchDemo(String name)
    {
        this.name = name;
    }

    @Override
    public void run()
    {
        for (int i = 0; i < 50; i++)
        {
            System.out.println("name:" + name + "============> " + i);
            try
            {
                Thread.sleep(10);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args)
    {
        List<Runnable> list = new ArrayList<>();
        list.add(new CountDownLatchDemo("A"));
        list.add(new CountDownLatchDemo("B"));
        list.add(new CountDownLatchDemo("C"));
        list.add(new CountDownLatchDemo("D"));
        list.add(new CountDownLatchDemo("E"));
        excutorRunables(executor, list);
        System.out.println("count:" + executor.getActiveCount());

//        list = new ArrayList<>();
//        list.add(new CountDownLatchDemo("E"));
//        list.add(new CountDownLatchDemo("F"));
//        list.add(new CountDownLatchDemo("G"));
//        list.add(new CountDownLatchDemo("H"));
//        list.add(new CountDownLatchDemo("I"));
//        excutorRunables(executor, list);
//        try
//        {
//            Thread.sleep(100);
//        } catch (InterruptedException e)
//        {
//            e.printStackTrace();
//        }

        new Thread(() ->
        {
            List<Runnable> runnableList = new ArrayList<>();
            runnableList.add(new CountDownLatchDemo("A"));
            runnableList.add(new CountDownLatchDemo("B"));
            runnableList.add(new CountDownLatchDemo("C"));
            runnableList.add(new CountDownLatchDemo("D"));
            runnableList.add(new CountDownLatchDemo("E"));
            excutorRunables(executor, runnableList);
            System.out.println("=========================================");
        }).start();

        new Thread(() ->
        {
            List<Runnable> runnableList = new ArrayList<>();
            runnableList.add(new CountDownLatchDemo("A1"));
            runnableList.add(new CountDownLatchDemo("B1"));
            runnableList.add(new CountDownLatchDemo("C1"));
            runnableList.add(new CountDownLatchDemo("D1"));
            runnableList.add(new CountDownLatchDemo("E1"));
            excutorRunables(executor, runnableList);
            System.out.println("++++++++++++++++++++++++++++++++++++++++++++++");
        }).start();
    }

    public static void excutorRunables(ExecutorService executor, Collection<? extends Runnable> runnableList)
    {
        final CountDownLatch start = new CountDownLatch(1);
        final CountDownLatch ready = new CountDownLatch(runnableList.size());
        final CountDownLatch end = new CountDownLatch(runnableList.size());
        runnableList
                .stream()
                .map(r -> (Runnable) () ->
                {
                    ready.countDown();
                    try
                    {
                        start.await();
                        r.run();
                    } catch (Exception e)
                    {
                        e.printStackTrace();
                    } finally
                    {
                        end.countDown();
                    }
                })
                .forEach(executor::execute);
        try
        {
            ready.await();
            start.countDown();
            end.await();
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
